package com.cmsz.cashier.controller;

import java.io.IOException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.cmsz.cashier.bean.CashierOrderInoBean;
import com.cmsz.cashier.mapper.CashierOrderInfoBeanMapper;
import com.cmsz.cashier.utils.CommonConstants;
import com.cmsz.cashier.utils.ParamUtil;
import com.cmsz.order.remote.AliRemoteService;
import com.cmsz.order.remote.BetterRemoteService;
import com.cmsz.order.remote.SignResult;
import com.cmsz.framework.exception.DefaultReturnCode;
import com.cmsz.framework.exception.UpayBusinessException;
import com.cmsz.framework.log.LogHandler;
import com.cmsz.framework.util.JsonUtil;
import com.cmsz.framework.util.KeyValueUtil;

/**
 * 处理支付宝回调
 * @author Eshin
 *
 */

@Controller
@RequestMapping("/cashier")
public class AliReturnUrlController {
	
	private static LogHandler logger = LogHandler.getLogger(AliReturnUrlController.class);
	@Resource(name="BankSecurityRemoting")
	private BetterRemoteService betterRemoteService;
	@Resource(name="aliRemoteService")
	private AliRemoteService aliRemoteService;
	@Autowired
	CashierOrderInfoBeanMapper cashierOrderInfoBeanMapper;
	@ResponseBody
	@RequestMapping(value = "/alireturn", produces = "text/html; charset=utf-8", method = { RequestMethod.POST,
			RequestMethod.GET })
	public ModelAndView aliReturn(HttpServletRequest req) throws IOException {
		CashierOrderInoBean orderBean = new CashierOrderInoBean();
		ModelAndView modelAndView = new ModelAndView();
//		1、接收到支付宝支付完成后回调
		try {
			Map<String, String> reqMap = comvertMap(req.getParameterMap());
			logger.messageReceive("收银台|AliReturnUrlController|接收到支付宝支付完成后响应数据："+reqMap.toString());
			logger.info("收银台|AliReturnUrlController|接收到支付宝支付后响应",null);
			
//		    2、设置基本信息Bean
			combineBean(orderBean,reqMap);
			logger.info("收银台|AliReturnUrlController|设置基本信息Bean完成",null);
			
//		    3、回调参数验签
			boolean isTrue = checkSign(reqMap);
			if(!isTrue){
			       throw new UpayBusinessException("支付宝验签异常", DefaultReturnCode.UPAY_015A03);
				}
			logger.info("收银台|AliReturnUrlController|支付宝验签完成",null);
			
//		    4、查找原订单
			CashierOrderInoBean oriOrderBean = cashierOrderInfoBeanMapper.selectList(orderBean).get(0);
			logger.info("收银台|AliReturnUrlController|查询原订单完成",null);
			
//		    5、设置回调参数
			Map<String, String> rspMap = setReturnParanm(oriOrderBean,reqMap);
			logger.info("收银台|AliReturnUrlController|设置商户回调参数完成",null);
			
//		    6、回调参数签名
			signToMerchant(rspMap);
			logger.info("收银台|AliReturnUrlController|回调商户参数签名完成",null);
			
//		    7、响应回调跳转页面
			modelAndView.addObject("rspMap", rspMap);
			modelAndView.setViewName(CommonConstants.RETURN_PAGE);
			logger.info("收银台|AliReturnUrlController|向用户响应return界面",null);
			logger.messageSend("收银台|AliReturnUrlController|向商户响应支付完成后数据："+rspMap.toString());
			return modelAndView;
		} catch (Exception e) {
			modelAndView.addObject("orderBean", orderBean);
			logger.error("收银台|AliReturnUrlController|接收支付宝支付后响应异常，向用户返回异常界面",e);
			modelAndView.setViewName(CommonConstants.ERROR_PAGE);
			return modelAndView;
		}
		
	}
	
	private Map<String, String> setReturnParanm(CashierOrderInoBean oriOrderBean, Map<String, String> reqMap) {
		Map<String, String> rspMap = ParamUtil.genMerReturnParam(oriOrderBean);
		String isSuccess =  reqMap.get("is_success");
		if("T".equals(isSuccess)){
			rspMap.put("RspCode", "010A00");
			rspMap.put("RspDesc", "成功");
		}else{
			throw new RuntimeException("银联返回非成功状态："+isSuccess );
		}
		return rspMap;
	}

	/**
	 * 对向商户return的报文签名
	 * @param reqMap
	 */
	private void signToMerchant(Map<String, String> reqMap) {
		try {
			reqMap.remove("sign");
			reqMap.remove("sign_type");
			String kv = KeyValueUtil.mapToString(reqMap);
			String jsonStr = betterRemoteService.sign(null, kv);
			SignResult signResult = JsonUtil.jsonStr2Obj(jsonStr, SignResult.class);
			String signValue = signResult.getSignValue();
			String cerId = signResult.getCerId();
			reqMap.put("CerID", cerId);
			reqMap.put("SignValue", signValue);
		} catch (Exception e) {
			
		}
	}

	/**
	 * 将http请求参数转换成Map<String, String>
	 * @param map
	 * @return
	 */
	private Map<String, String> comvertMap(Map<String, String[]> map) {
		Map<String, String> newMap = new HashMap<String, String>();
		Iterator<Entry<String, String[]>> it = map.entrySet().iterator();
		while (it.hasNext()) {
			Entry<String, String[]> entry = it.next();
			String key = entry.getKey();
			String[] value = entry.getValue();
			newMap.put(key, value[0]);
		}
		return newMap;
	}
	
	/**
	 * 对支付宝的签名进行验签
	 * @param reqMap
	 * @return 
	 */
	private boolean checkSign(Map<String, String> reqMap) {
		try {
			String signature = reqMap.remove("sign");
			reqMap.remove("sign_type");
			String plainText = KeyValueUtil.mapToString(reqMap);
			return aliRemoteService.verifyRsa(null, plainText, signature);
		} catch (Exception e) {
			throw new UpayBusinessException("支付宝验签失败", DefaultReturnCode.UPAY_015A03);
		}
	}
	
	/**
	 * 组装bean中必要参数
	 * @param orderBean
	 * @param reqMap
	 */
	private void combineBean(CashierOrderInoBean orderBean, Map<String, String> reqMap) {
		String orderNo = reqMap.get("out_trade_no");
//		设置查询bean
		orderBean.setOrderNo(orderNo);
		orderBean.setReqSys(orderNo.substring(0, 4));
		orderBean.setReqDate(orderNo.substring(4, 12));
	}
}
